package cn.com.pagoda.ideplugin.ui;

import cn.com.pagoda.ideplugin.common.transcoder.TranscoderAlgorithmEnum;
import cn.com.pagoda.ideplugin.common.transcoder.TranscoderTypeEnum;
import cn.com.pagoda.ideplugin.listener.KeyFieldMouseListener;
import cn.com.pagoda.ideplugin.listener.TranscoderActionListener;
import cn.com.pagoda.ideplugin.service.TranscoderService;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 转码器工具页
 *
 * @author 谢璐鑫 on 2023-05-06
 */
public class TranscoderPanel {

    private final TranscoderService service;
    private final AnActionEvent anActionEvent;
    //当前页主panel
    //可通过按钮切换的子panel
    private JPanel subPagePanel;
    private CardLayout subPageCardLayout;
    //工具条上转码器类型按钮
    private JButton encryptAndDecryptBtn,
            hashCalculateBtn,
            encodeAndDecodeBtn;

    //算法list
    private List<String> encodeAlgorithmShowList = new ArrayList<>(),
            hashAlgorithmShowList = new ArrayList<>(),
            encryptAlgorithmShowList = new ArrayList<>();

    /**
     * 转码器panel构建函数
     *
     * @param anActionEvent
     * @param mainPanel
     */
    public TranscoderPanel(AnActionEvent anActionEvent, JPanel mainPanel) {
        this.anActionEvent = anActionEvent;
        service = new TranscoderService();
        JPanel pagePanel = new JPanel(new BorderLayout());
        //初始化所有算法
        initSelectData();
        //初始化工具条,并给按钮添加监听器
        TranscoderActionListener frameListener = new TranscoderActionListener(this);
        JToolBar toolBar = initToolBar(frameListener);
        //初始化所有子panel
        initSubPanel();

        //设置布局
        pagePanel.add(toolBar, BorderLayout.NORTH);
        subPagePanel.setBackground(Color.ORANGE);
        pagePanel.add(subPagePanel, BorderLayout.CENTER);
        mainPanel.add(pagePanel, getClass().getSimpleName());
    }

    /**
     * 编码/解码子页面
     */
    private void buildEncodeAndDecodeSubPanel() {
        //创建上部区域, 包含明文输入框
        JPanel encodeAndDecodeSubPanel = new JPanel(new GridBagLayout());
        JPanel upperPanel = new JPanel(new BorderLayout());
        JTextArea plaintextArea = new JTextArea();
        plaintextArea.setToolTipText("Tip: enter/display plaintext here");
        upperPanel.add(new JScrollPane(plaintextArea), BorderLayout.CENTER);


        // 创建中间区域，包括加密算法下拉选择框,编码按钮,解码按钮
        FlowLayout flowLayout = new FlowLayout();
        JPanel middlePanel = new JPanel(flowLayout);
        JButton selectEncodeAlgorithmButton = new JButton("▽ Please select an encoding algorithm");
        selectEncodeAlgorithmButton.addActionListener(e -> showAlgorithmPopup(selectEncodeAlgorithmButton, encodeAlgorithmShowList));
        middlePanel.add(selectEncodeAlgorithmButton);
        JButton encodeButton = new JButton("encoding ↓");
        middlePanel.add(encodeButton);

        JButton decodeButton = new JButton("decoding ↑");
        middlePanel.add(decodeButton);

        // 创建下部区域，包括解码后文本输入框
        JPanel lowerPanel = new JPanel(new BorderLayout());
        JTextArea ciphertextArea = new JTextArea();
        ciphertextArea.setToolTipText("Tip: enter/display encoded text here");
        lowerPanel.add(new JScrollPane(ciphertextArea), BorderLayout.CENTER);

        //添加按钮监听
        encodeButton.addActionListener(event -> {
            try {
                ciphertextArea.setText(service.
                        encodeByContent(plaintextArea.getText(), TranscoderAlgorithmEnum.getByCode(selectEncodeAlgorithmButton.getText())));
            } catch (Exception e) {
                JOptionPane.showMessageDialog(encodeAndDecodeSubPanel, e.getMessage());
            }
        });
        decodeButton.addActionListener(event -> {
            try {
                plaintextArea.setText(service.
                        decodeByContent(ciphertextArea.getText(), TranscoderAlgorithmEnum.getByCode(selectEncodeAlgorithmButton.getText())));
            } catch (Exception e) {
                JOptionPane.showMessageDialog(encodeAndDecodeSubPanel, e.getMessage());
            }
        });

        //设置布局
        encodeAndDecodeSubPanel.add(upperPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 0, 1, 1));
        encodeAndDecodeSubPanel.add(middlePanel, addPanelToLayout(GridBagConstraints.NONE, 0, 1, 0, 0));
        encodeAndDecodeSubPanel.add(lowerPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 2, 1, 1));
        subPagePanel.add(encodeAndDecodeSubPanel, TranscoderTypeEnum.ENCODE_AND_DECODE_SUB_PANEL.getCode());
    }

    /**
     * 设置GridBagConstraints
     *
     * @param fill    边缘填充策略
     * @param gridx   x坐标
     * @param gridy   y坐标
     * @param weightx x权重
     * @param weighty y权重
     * @return
     */
    private GridBagConstraints addPanelToLayout(int fill, int gridx, int gridy, double weightx, double weighty) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = gridx;
        gbc.gridy = gridy;
        gbc.fill = fill;
        gbc.weightx = weightx;
        gbc.weighty = weighty;
        return gbc;
    }

    /**
     * 初始化算法list
     */
    private void initSelectData() {
        for (TranscoderAlgorithmEnum algorithmEnum : TranscoderAlgorithmEnum.values()) {
            TranscoderTypeEnum transcoderTypeEnum = algorithmEnum.getTranscoderTypeEnum();
            if (transcoderTypeEnum.equals(TranscoderTypeEnum.ENCODE_AND_DECODE_SUB_PANEL)) {
                encodeAlgorithmShowList.add(algorithmEnum.getCode());
            } else if (transcoderTypeEnum.equals(TranscoderTypeEnum.ENCRYPT_AND_DECRYPT_SUB_PANEL)) {
                encryptAlgorithmShowList.add(algorithmEnum.getCode());
            } else if (transcoderTypeEnum.equals(TranscoderTypeEnum.HASH_CALCULATE_SUB_PANEL)) {
                hashAlgorithmShowList.add(algorithmEnum.getCode());
            }
        }
    }

    /**
     * 算法下拉选择
     */
    private void showAlgorithmPopup(JButton algorithmButton, List<String> algorithmShowList) {
        JBPopupFactory.getInstance().createListPopup(
                new BaseListPopupStep<>("Choose a algorithm", algorithmShowList) {
                    @Override
                    public PopupStep onChosen(String selectedValue, boolean finalChoice) {
                        algorithmButton.setText(selectedValue);
                        return super.onChosen(selectedValue, finalChoice);
                    }
                }
        ).showUnderneathOf(algorithmButton);
    }


    /**
     * 构建加密/解密子页面
     */
    private void buildEncryptAndDecryptSubPanel() {
        JPanel encryptAndDecryptSubPanel = new JPanel(new GridBagLayout());
        //创建上部区域, 包含明文输入框
        JPanel upperPanel = new JPanel(new BorderLayout());
        JTextArea plaintextArea = new JTextArea();
        plaintextArea.setToolTipText("Tip: enter/display plaintext here");
        upperPanel.add(new JScrollPane(plaintextArea), BorderLayout.CENTER);


        // 创建中间区域，包括加密算法下拉选择框,加密按钮,解密按钮
        JPanel middlePanel = new JPanel(new FlowLayout());
        JButton selectEncryptAlgorithmButton = new JButton("▽ Please select an encryption algorithm");
        selectEncryptAlgorithmButton.addActionListener(e -> showAlgorithmPopup(selectEncryptAlgorithmButton, encryptAlgorithmShowList));
        middlePanel.add(selectEncryptAlgorithmButton);

        JTextField keyField = new JTextField(10);
        keyField.setText("please enter key:");
        middlePanel.add(keyField);
        keyField.addMouseListener(new KeyFieldMouseListener(keyField));

        JButton encryptButton = new JButton("encryption ↓");
        middlePanel.add(encryptButton);

        JButton decryptButton = new JButton("decrypt ↑");
        middlePanel.add(decryptButton);

        // 创建下部区域，包括解码后文本输入框
        JPanel lowerPanel = new JPanel(new BorderLayout());
        JTextArea ciphertextArea = new JTextArea();
        ciphertextArea.setToolTipText("Tip: Enter/display encrypted text here");
        lowerPanel.add(new JScrollPane(ciphertextArea), BorderLayout.CENTER);

        //添加按钮监听
        encryptButton.addActionListener(event -> {
            try {
                ciphertextArea.setText(service.encryptByContent(plaintextArea.getText(),keyField.getText()
                        , TranscoderAlgorithmEnum.getByCode(selectEncryptAlgorithmButton.getText())));
            } catch (Exception e) {
                JOptionPane.showMessageDialog(encryptAndDecryptSubPanel, e.getMessage());
            }
        });
        decryptButton.addActionListener(event -> {
            try {
                plaintextArea.setText(service.decryptByContent(ciphertextArea.getText(),keyField.getText()
                        , TranscoderAlgorithmEnum.getByCode(selectEncryptAlgorithmButton.getText())));
            } catch (Exception e) {
                JOptionPane.showMessageDialog(encryptAndDecryptSubPanel, e.getMessage());
            }
        });

        //设置布局
        encryptAndDecryptSubPanel.add(upperPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 0, 1, 1));
        encryptAndDecryptSubPanel.add(middlePanel, addPanelToLayout(GridBagConstraints.NONE, 0, 1, 0, 0));
        encryptAndDecryptSubPanel.add(lowerPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 2, 1, 1));
        subPagePanel.add(encryptAndDecryptSubPanel, TranscoderTypeEnum.ENCRYPT_AND_DECRYPT_SUB_PANEL.getCode());
    }

    /**
     * 构建计算hash值子页面
     */
    private void buildHashCalculateSubPanel() {
        JPanel hashCalculateSubPanel = new JPanel(new GridBagLayout());
        //创建上部区域, 包含明文输入框
        JPanel upperPanel = new JPanel(new BorderLayout());
        JTextArea plaintextArea = new JTextArea();
        plaintextArea.setToolTipText("Tip: enter/display plaintext here");
        upperPanel.add(new JScrollPane(plaintextArea), BorderLayout.CENTER);


        // 创建中间区域，包括Hash算法下拉选择框,计算按钮
        JPanel middlePanel = new JPanel(new FlowLayout());
        JButton selectHashAlgorithmButton = new JButton("▽ Please choose hash algorithm");
        selectHashAlgorithmButton.addActionListener(e -> showAlgorithmPopup(selectHashAlgorithmButton, hashAlgorithmShowList));
        middlePanel.add(selectHashAlgorithmButton);


        JButton calculateButton = new JButton("Hash calculation ↓");
        middlePanel.add(calculateButton);


        // 创建下部区域，包括Hash值展示框
        JPanel lowerPanel = new JPanel(new BorderLayout());
        JTextArea ciphertextArea = new JTextArea();
        ciphertextArea.setToolTipText("Tip: This is used to display the Hash value");
        ciphertextArea.setEnabled(false);
        lowerPanel.add(new JScrollPane(ciphertextArea), BorderLayout.CENTER);


        //添加按钮监听
        calculateButton.addActionListener(event -> {
            try {
                ciphertextArea.setText(service.calculateHashByContent(plaintextArea.getText(),null
                                , TranscoderAlgorithmEnum.getByCode(selectHashAlgorithmButton.getText())));
            } catch (Exception e) {
                JOptionPane.showMessageDialog(hashCalculateSubPanel, e.getMessage());
            }
        });

        //设置布局
        hashCalculateSubPanel.add(upperPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 0, 1, 1));
        hashCalculateSubPanel.add(middlePanel, addPanelToLayout(GridBagConstraints.NONE, 0, 1, 0, 0));
        hashCalculateSubPanel.add(lowerPanel, addPanelToLayout(GridBagConstraints.BOTH, 0, 2, 1, 1));
        subPagePanel.add(hashCalculateSubPanel, TranscoderTypeEnum.HASH_CALCULATE_SUB_PANEL.getCode());
    }


    /**
     * 初始化工具条
     *
     * @param frameListener
     * @return
     */
    private JToolBar initToolBar(TranscoderActionListener frameListener) {
        JToolBar toolBar = new JToolBar();
        toolBar.setLayout(new GridLayout(1, 3));
        toolBar.setBorder(BorderFactory.createEmptyBorder());
        toolBar.setFloatable(false);
        //添加顶部菜单按钮
        encodeAndDecodeBtn = new JButton(TranscoderTypeEnum.ENCODE_AND_DECODE_SUB_PANEL.getMsg());
        encodeAndDecodeBtn.addActionListener(frameListener);
        toolBar.add(encodeAndDecodeBtn);

        encryptAndDecryptBtn = new JButton(TranscoderTypeEnum.ENCRYPT_AND_DECRYPT_SUB_PANEL.getMsg());
        encryptAndDecryptBtn.addActionListener(frameListener);
        toolBar.add(encryptAndDecryptBtn);

        hashCalculateBtn = new JButton(TranscoderTypeEnum.HASH_CALCULATE_SUB_PANEL.getMsg());
        hashCalculateBtn.addActionListener(frameListener);
        toolBar.add(hashCalculateBtn);
        return toolBar;
    }

    /**
     * 初始化可切换的子panel
     */
    public void initSubPanel() {
        subPagePanel = new JPanel(new BorderLayout());
        subPageCardLayout = new CardLayout();
        subPagePanel.setLayout(subPageCardLayout);
        buildEncodeAndDecodeSubPanel();
        buildEncryptAndDecryptSubPanel();
        buildHashCalculateSubPanel();
    }



    //=============get/set方法===============//
    public AnActionEvent getAnActionEvent() {
        return anActionEvent;
    }

    public JButton getEncryptAndDecryptBtn() {
        return encryptAndDecryptBtn;
    }

    public JButton getHashCalculateBtn() {
        return hashCalculateBtn;
    }

    public JButton getEncodeAndDecodeBtn() {
        return encodeAndDecodeBtn;
    }

    public CardLayout getSubPageCardLayout() {
        return subPageCardLayout;
    }

    public JPanel getSubPagePanel() {
        return subPagePanel;
    }
}
